package cc.wanforme.st.server.base.service.impl;

import cc.wanforme.st.server.authen.dto.UserRoleAuth;
import cc.wanforme.st.server.authen.service.TokenService;
import cc.wanforme.st.server.base.constant.UserStatus;
import cc.wanforme.st.server.base.entity.AuthToken;
import cc.wanforme.st.server.base.entity.RolePermission;
import cc.wanforme.st.server.base.entity.User;
import cc.wanforme.st.server.base.entity.UserRole;
import cc.wanforme.st.server.base.mapper.UserMapper;
import cc.wanforme.st.server.base.service.IRolePermissionService;
import cc.wanforme.st.server.base.service.IUserRoleService;
import cc.wanforme.st.server.base.service.IUserService;
import cc.wanforme.st.server.util.AssertCheck;
import cc.wanforme.st.server.util.PasswordUtil;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author wanne
 * @since 2023-01-03
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
	implements IUserService {

	@Autowired
	private TokenService tokenService;
	@Autowired
	private IUserRoleService roleService;
	@Autowired
	private IRolePermissionService roleAuthService;
	
	/** 根据 token 查出对应用户的角色和权限<br> 
	 * token 不存在时，会跑出异常
	 * @param token
	 * @return
	 */
	public UserRoleAuth selectAuthenticationsByToken(String token) {
		Long userId = tokenService.getIdByToken(token);
		
		if(userId==null) {
			AuthToken authToken = tokenService.selectValidToken(token);
			Assert.notNull(authToken, "登录信息已过期");
			userId = authToken.getUserId();
		}
		
		Assert.notNull(userId, "请先登录");
		
		return this.selectAuthenticationsByUser(userId);
	}
	
	/** 获取用户的角色和权限（建议加入缓存）<br>
	 * 注：没有查询 User 信息
	 * @param userId
	 * @return
	 */
	public UserRoleAuth selectAuthenticationsByUser(long userId) {
		UserRoleAuth re = new UserRoleAuth();
		List<UserRole> roles = roleService.selectRoles(userId);
		User user = this.getById(userId);
		
		Assert.notNull(user, "未查到此用户");
		re.setUser(user);;
		
		if(roles==null) {
			return re;
		}
		
		for (UserRole role : roles) {
			List<RolePermission> auths = roleAuthService.selectPermissions(role.getRole());
			if(auths == null) {
				auths = new ArrayList<>(0);
			}
			re.getRoleAuth().put(role, auths);
		}
		
		return re;
	}
	
	@Override
	public User selectUserByToken(String token) {
		Long userId = tokenService.getIdByToken(token);
		if(userId==null) {
			AuthToken authToken = tokenService.selectValidToken(token);
			Assert.notNull(authToken, "用户登录信息已过期");
			userId = authToken.getUserId();
		}
		
		if(userId==null) {
			return null;
		}
		
		User user = this.getById(userId);
		return user;
	}

	@Override
	public User selectByUsername(String username) {
		return this.baseMapper.selectByUsername(username);
	}

	@Override
	public User saveVo(User vo) {
		AssertCheck.nonNull(vo.getName(), "缺少昵称");
		AssertCheck.nonNull(vo.getUsername(), "缺少用户名");
		AssertCheck.nonNull(vo.getPassword(), "缺少密码");
		
		vo.setPassword(PasswordUtil.encodePassword(vo.getPassword()));
		
		this.save(vo);
		return vo;
	}

	@Override
	public void updateVo(User vo) {
		AssertCheck.nonNull(vo.getId(), "未知用户");
		AssertCheck.nonNull(vo.getName(), "缺少昵称");
		AssertCheck.nonNull(vo.getUsername(), "缺少用户名");
		
		vo.setPassword(null);
		this.updateById(vo);
	}
	
	@Override
	public void resetPwd(Long id, String password) {
		AssertCheck.nonNull(password, "请输入新密码");
		
		User po = this.getById(id);
		AssertCheck.nonNull(po, "用户不存在!");
		
		po.setPassword(PasswordUtil.encodePassword(password));
		this.updateById(po);
	}

	@Override
	public void deleteUser(String id) {
		User user = this.getById(id);
		AssertCheck.nonNull(user, "用户不存在");
		
		user.setStatus(UserStatus.DELETE.getCode());
		this.updateById(user);
	}

	@Override
	public void resetPassword(String userId, String password) {
		User user = this.getById(userId);
		AssertCheck.nonNull(user, "用户不存在");
		
		user.setPassword(PasswordUtil.encodePassword(password));
		this.updateById(user);
	}

	
	@Override
	public PageInfo<User> searchUsers(int page, int pageSize, String name,
			String username, String status) {
		PageHelper.startPage(page, pageSize);
		List<User> list = this.baseMapper.listUsers(name, username, status);
		return new PageInfo<User>(list);
	}
	
}
